package com.lottery.game.core.modules.service.app;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.lottery.game.common.constants.GameConstants;
import com.lottery.game.common.utils.DateUtils;
import com.lottery.game.core.model.websocket.CustomerMessage;
import com.lottery.game.core.model.websocket.InboundCustomerMessage;
import com.lottery.game.core.model.websocket.InboundCustomerServiceSystemMessage;
import com.lottery.game.core.model.websocket.InboundRoomMessage;
import com.lottery.game.core.model.websocket.OutboundMessage;
import com.lottery.game.core.model.websocket.WebSocketStatus;
import com.lottery.game.core.modules.entity.user.ChatRecord;
import com.lottery.game.core.modules.entity.user.GameUser;
import com.lottery.game.core.modules.entity.user.UserRankPojo;
import com.lottery.game.core.modules.service.game.SysDictService;
import com.lottery.game.core.modules.service.redis.RedisService;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class WebSocketService {

	@Autowired
	private SimpMessagingTemplate template;

	@Autowired
	private RedisService redisFeignClient;

	@Autowired
	private GameUserService gameUserService;

	@Autowired
	private ChatRecordService chatRecordService;

	@Autowired
	private OnlineAppContext onlineAppContext;

	@Autowired
	private UserRankService userRankService;
	
	@Autowired
	private SysDictService sysDictService;
	
	List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

	/**
	 * 功能描述：发送在线用户
	 */
	public void sendOnlineUser() {
		int onlineCount = 0;

		Set<String> set = new HashSet<>();

		try {
			// 获取所有USERID开头的记录
			// USERID开头的记录是在用户登录时， 调用UserLoginService.getGameUserBynamepwd生成的
			// key: USERIDxxxx value: 登录的时间
			set = redisFeignClient.keys("USERID*");

			set.stream().forEach(userIdKey -> {
				long currentTime = System.currentTimeMillis();// 当前时间
				String val = redisFeignClient.get(userIdKey);
				long loginTime = Long.parseLong(val); // 用户的时间

				// 登录时间和当前时间相差的时间
				long time = currentTime - loginTime;

				// 相差时间超过600秒
				if (time >= 600000) {// 3600000

					Map<String, Object> map = new HashMap<>();

					String userId = userIdKey.substring(6, userIdKey.length());

					map.put("userOnlineStatus", "0");
					map.put("userId", userId);

					list.add(map);

					// 下面2句为什么从redis删除
					redisFeignClient.delete(userIdKey);
					redisFeignClient.delete("UUID" + userId);
				}
			});

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}

		if (!CollectionUtils.isEmpty(list)) {
			int num = gameUserService.updateBatchUserOnlineStatus(list);
			if (num > 0)
				list.clear();
		}

		onlineCount = set.size() - list.size();
		RealNumberObj realNumber = new RealNumberObj();
		realNumber.setRoomPeople(onlineCount);
		realNumber.setRandomNumber(0);
		realNumber.setStatus("add");

		RoomRealNumberObj rn = new RoomRealNumberObj(realNumber);

		String sendMsgJson = JSONObject.toJSONString(rn);
		template.convertAndSend("/topic/broadcast", new OutboundMessage(WebSocketStatus.ONLINE_USER, sendMsgJson));
	}

	public void sendToTheUser(final String jsonFormatContent, String userId, String chatId, String roomNumber) {
//		CopyOnWriteArrayList<String> userIds = OnlineAppContext.getUserIds(chatId);
//		if(CollectionUtils.isEmpty(userIds)) return;

//		if(userIds.contains(userId)) {
		String url = "/topic/game/" + userId;
		if (StringUtils.isNotBlank(roomNumber)) {
			url = "/topic/game/BET_ROOM_" + roomNumber + "_" + userId;
		}
		if (StringUtils.isNotBlank(chatId)) {
			url = "/topic/game/" + chatId + userId;
		}
		log.info("sendToTheUser::chatId:::" + chatId);
		log.info("sendToTheUser::userId:::" + userId);
		log.info("sendToTheUser::url:::" + url);
		template.convertAndSend(url, new OutboundMessage(WebSocketStatus.BASIC_TEXT_CHAT, jsonFormatContent));
//		}
	}

	/**
	 * 发送实体给用户
	 * 
	 * @param message
	 * @param userId
	 */
	public void sendToUser(final Object message, String userId) {
		sendToTheUser(JSON.toJSONString(message), userId, null, null);
	}

//	public void sendToEveryChatUser(final String jsonFormatContent, String chatId) {
//		Set<String> userIds = onlineAppContext.getUserIds(chatId);
//
//		userIds.stream().forEach(userId -> {
//			TextMessage message = new TextMessage(jsonFormatContent);
//			template.convertAndSend("/topic/broadcast",
//					new OutboundMessage(WebSocketStatus.BROADCAST_TEXT_CHAT, message));
//		});
//	}

	public void sendToTheUser(CustomerMessage message) {
		// user->cs
		if (message instanceof InboundCustomerMessage) {
			InboundCustomerMessage m = (InboundCustomerMessage) message;
			
			GameUser user = gameUserService.get(m.getUserId());
			// 获取用户等级信息
			UserRankPojo userRank = new UserRankPojo();
			userRank.setQueryAmount(user.getBalance());
			UserRankPojo userRankPojo = userRankService.getUserRank(userRank);
			m.setLevel_photourl(userRankPojo == null ? "" : sysDictService.findImageServerAddress() + userRankPojo.getLevelPhotourl());
			this.saveUserCustomerServiceChatRecord(m,user,userRankPojo);

			log.info("---InboundCustomerMessage---userId: {}", m.getUserId());

			// user endpoint
			template.convertAndSend("/topic/game/" + m.getChatId(),
					new OutboundMessage(WebSocketStatus.CS_CUSTOMER_MSG, message));

			// cs endpoint
			template.convertAndSend("/queue/game/" + m.getChatId(),
					new OutboundMessage(WebSocketStatus.CS_CUSTOMER_MSG, message));
		}

		// cs->user
		if (message instanceof InboundCustomerServiceSystemMessage) {
			InboundCustomerServiceSystemMessage m = (InboundCustomerServiceSystemMessage) message;
			this.saveSystemCustomerServiceChatRecord(m);

			log.info("---InboundCustomerServiceSystemMessage---");

			// cs endpoint
			template.convertAndSend("/queue/game/" + m.getUserId(),
					new OutboundMessage(WebSocketStatus.CS_SYSTEM_MSG, message));

			// user endpoint
			template.convertAndSend("/topic/game/" + m.getUserId(),
					new OutboundMessage(WebSocketStatus.CS_SYSTEM_MSG, message));
		}
	}

	private ChatRecord saveUserCustomerServiceChatRecord(InboundCustomerMessage message,GameUser user,UserRankPojo userRankPojo) {
		
		String messageContent = JSON.toJSONString(message);

		ChatRecord chatRecord = new ChatRecord();
		UUID uuid = UUID.randomUUID();
		chatRecord.setId(uuid.toString());
		chatRecord.setChatType(message.getChatId());
		chatRecord.setSenderUserid(message.getUserId());
		chatRecord.setMsgContent(messageContent);
		chatRecord.setSendernickname(message.getSendernickname());
		chatRecord.setMessageStatus("0");
		chatRecord.setTimestamp(DateUtils.getNowDateString());
		chatRecord.setSenderPhone(user.getPhone());
		// chatRecord.setSendernickname(user.getUsername());
		chatRecord.setSenderphoto(user.getPhotourl());
		chatRecord.setOrginMsg(message.getMessage());
		
		chatRecord.setLevel_photourl(userRankPojo==null?"":userRankPojo.getLevelPhotourl());
		chatRecordService.addChatRecord(chatRecord);

		return chatRecord;
	}

	private ChatRecord saveSystemCustomerServiceChatRecord(InboundCustomerServiceSystemMessage message) {
		String userId = message.getUserId();
		GameUser user = gameUserService.get(userId);
		String messageContent = JSON.toJSONString(message);

		ChatRecord chatRecord = new ChatRecord();
		UUID uuid = UUID.randomUUID();
		chatRecord.setId(uuid.toString());
		chatRecord.setChatType(GameConstants.CHATTYPE_CUSREPLY);
		chatRecord.setMsgContent(messageContent);
		chatRecord.setSenderPhone(null);
		chatRecord.setSendernickname(message.getSenderNickname());
		chatRecord.setSenderUserid(message.getSenderUserId());
		chatRecord.setReceiverUserid(userId);
		chatRecord.setReceiverPhone(user.getPhone());
		chatRecord.setMessageStatus("0");
		chatRecord.setTimestamp(DateUtils.getNowDateString());
		chatRecord.setOrginMsg(message.getMessage());

		chatRecordService.addChatRecord(chatRecord);

		return chatRecord;
	}

	public void sendRoomMessage(InboundRoomMessage message) {
		ChatRecord chatRecord = new ChatRecord();
		UUID uuid = UUID.randomUUID();
		chatRecord.setId(uuid.toString());
		String chatId = message.getChatId();
		String userId = message.getUserId();
		String roomNumber = message.getRoomNumber();
		String senderPhone = message.getSenderPhone();
		String msg = message.getMessage();
		String sendernickname = message.getSendernickname();
		String photourl = message.getPhotourl();
		String senderUserId = message.getSenderUserId();

		log.info("   ----senderUserId: {}", senderUserId);

		chatRecord.setRoomnumber(chatId);
		GameUser user = gameUserService.get(message.getSenderUserId());
		if (user != null) {
			chatRecord.setSenderPhone(user.getPhone());
			chatRecord.setSendernickname(user.getUsername());
			chatRecord.setSenderphoto(user.getPhotourl());
			
			// 获取用户等级信息
			UserRankPojo userRank = new UserRankPojo();
			userRank.setQueryAmount(user.getBalance());
			UserRankPojo userRankPojo = userRankService.getUserRank(userRank);
			chatRecord.setLevel_photourl(userRankPojo == null ? "" : userRankPojo.getLevelPhotourl());
			message.setLevel_photourl(userRankPojo == null ? "" : sysDictService.findImageServerAddress() + userRankPojo.getLevelPhotourl());
		} else {
			chatRecord.setSenderPhone("null");
			chatRecord.setSendernickname(message.getSenderUserId());
		}

		chatRecord.setRoomnumber(roomNumber);
		chatRecord.setSenderPhone(senderPhone);
		chatRecord.setTimestamp(DateUtils.getNowDateString());
		chatRecord.setSendernickname(sendernickname);
		chatRecord.setSenderUserid(senderUserId);
		chatRecord.setSenderphoto(photourl);
		chatRecord.setMsgContent(JSON.toJSONString(message));
		chatRecord.setChatType(GameConstants.CHATTYPE_GROUPCHAT);
		chatRecord.setMessageStatus("0");
		chatRecord.setOrginMsg(msg);

		JSONObject jsObj = JSON.parseObject(chatRecord.getMsgContent());
		String orginMsg = jsObj.getString("message");
		chatRecord.setOrginMsg(orginMsg);

		chatRecordService.addChatRecord(chatRecord);

		Set<String> userIds = onlineAppContext.getUserIdsByRoomNumber(roomNumber);

		if (!CollectionUtils.isEmpty(userIds)) {

			log.info("   ---userIds[0]:  ", userIds);

			userIds.forEach(uId -> {
				sendToTheUser(JSON.toJSONString(message), uId, null, null);
			});
		}
	}

	@Data
	public class RealNumberObj implements Serializable {
		private static final long serialVersionUID = -8767942659854279321L;

		private String roomNumber;
		private int roomPeople;
		private String status;
		private int randomNumber;
	}

	@AllArgsConstructor
	@Data
	public class RoomRealNumberObj implements Serializable {

		private static final long serialVersionUID = 7132266850648287874L;

		@JSONField(name = "roomRealNumber")
		private RealNumberObj realNumberObj;
	}

}
